// <copyright file="DynamicArrayEnumeratorTests.cs" company="Sinbadsoft">
//        Copyright (c) Sinbadsoft 2009.
//        This file is released under the terms of the
//        GNU Library General Public License (LGPL) version 2.1
//        Please refer to the "License.txt" accompanying this file.
// </copyright>
// <author>Chaker NAKHLI</author>
// <email>Chaker.Nakhli@Sinbadsoft.com</email>
// <date>2009/04/14</date>

namespace Sinbadsoft.AdvancedCollections.Tests.DynamicArray
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using MbUnit.Framework;

    /// <summary>
    /// Tests the <see cref="DynamicArray{T}"/> enumeration.
    /// </summary>
    /// <remarks> This class ensure the specification stated in 
    /// <see url="http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx"/> is correctly 
    /// implemented.</remarks>
    [TestFixture]
    public static class DynamicArrayEnumeratorTests
    {
        public delegate void Invalidator_Delegate<T>(DynamicArray<T> darray);

        [StaticTestFactory]
        public static IEnumerable<Test> BuildTests()
        {
            IList<Test> tests = new List<Test>();

            tests.Add(new TestCase(
                  "Invalidate - SetValue()",
                  delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.SetValue(10, 10, 120); }); }));

            tests.Add(new TestCase(
                "Invalidate - Indexer Set",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da[10, 10] = 120; }); }));

            tests.Add(new TestCase(
                "Invalidate - Insert",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.Insert(new int[,] { { 10 } }, 0, 3, 3); }); }));

            tests.Add(new TestCase(
                "Invalidate - Clear",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.Clear(); }); }));

            tests.Add(new TestCase(
                "Invalidate - Resize : Grow",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.Resize(100, 100); }); }));

            tests.Add(new TestCase(
                "Invalidate - Resize : Shrink",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.Resize(2, 2); }); }));

            tests.Add(new TestCase(
                "Invalidate - ResizeDim : Grow",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.ResizeDim(0, 100); }); }));

            tests.Add(new TestCase(
                "Invalidate - ResizeDim : Shrink",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.ResizeDim(1, 3); }); }));

            tests.Add(new TestCase(
                "Invalidate - Extend",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.Extend(10, 10); }); }));

            tests.Add(new TestCase(
                "Invalidate - ExtendDim",
                delegate { InvalidateEnumerator(delegate(DynamicArray<int> da) { da.ExtendDim(0, 20); }); }));

            return tests;
        }

        [Test]
        public static void AsGenericCollection()
        {
            int[] data = new int[] { 3, 2, 4, 5, 7, -3, -2, -4, -5, -7 };
            DynamicArray<int> darray = new DynamicArray<int>(1);
            darray.Insert(data, 0, 0);

            Assert.AreElementsEqual(data, darray);
        }

        [Test]
        public static void AsNonGenericCollection()
        {
            int[] data = new int[] { 3, 2, 4, 5, 7, -3, -2, -4, -5, -7 };
            DynamicArray<int> darray = new DynamicArray<int>(1);
            darray.Insert(data, 0, 0);

            int i = 0;
            foreach (int element in (IEnumerable)darray)
            {
                Assert.AreEqual(data[i++], element);
            }
        }

        private static void InvalidateEnumerator(Invalidator_Delegate<int> invalidator)
        {
            // Build a DynamicArray
            DynamicArray<int> darray = new DynamicArray<int>(2);
            darray.Insert(new int[,] { { 3, 2, 4, 5, 7 }, { -3, -2, -4, -5, -7 } }, 0, 0, 0);

            // Get the IEnumerator<T>
            IEnumerator<int> enumerator = darray.GetEnumerator();

            // Advance on step and check current value
            enumerator.MoveNext();
            Assert.AreEqual(3, enumerator.Current);

            // Invalidate the array
            invalidator(darray);

            // Current must *NOT* rhrow if invalidation is right after MoveNext
            // see http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx
            Assert.AreEqual(3, enumerator.Current);

            // Move the invalidated enumerator (InvalidOperationException expected)
            Assert.Throws<InvalidOperationException>(delegate { enumerator.MoveNext(); });

            // Reset the invalidated enumerator (InvalidOperationException expected)
            Assert.Throws<InvalidOperationException>(delegate { enumerator.Reset(); });
        }
    }
}
